package de.uni.extededtab;


import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.widget.MediaController;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.VideoView;
import at.abraxas.amarino.Amarino;

public class MainActivity extends Activity {

	private static final String ARDUINO_ADDRESS = "00:07:80:90:8A:A8";
	private static final String TAG = "ExtMediaTab";
	private long lastChange;
	private final int DELAY = 150;
	
	private String VIDEO_NAME = "/one.mp4"; //farben
	//private String VIDEO_NAME = "/two.mp4"; //anime intros
	//private String VIDEO_NAME = "/test.avi"; //video
	//private String VIDEO_NAME = "/LeuchtendeKugel.mp4";

	protected ProgressBar mProgressBar;
	protected VideoView videoView;
	protected TextView sendText;
	protected MediaController mediaController;
	protected MediaMetadataRetriever retriever = new MediaMetadataRetriever();
	protected Bitmap bitmap;
	protected int[] pixels;
	protected Uri uri;
 
           
    
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		
			
		
		
		
		
		// Video
		uri = Uri.parse(Environment.getExternalStorageDirectory().getAbsolutePath()+ VIDEO_NAME);
		videoView = (VideoView) findViewById(R.id.videoView);
		
		mediaController = new MediaController(this);
		mediaController.setAnchorView(videoView);
		
		mProgressBar = (ProgressBar) findViewById(R.id.Progressbar);
		mProgressBar.setProgress(0);
		mProgressBar.setMax(100);
		
		videoView.setMediaController(mediaController);
		videoView.setVideoURI(uri);
		videoView.requestFocus();
		

		
		// Amarino
		Amarino.connect(this, ARDUINO_ADDRESS);
	
		
		
	

		
		// set initial lightning
		
	/*	Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'a', 255);
		Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'b', 0);
		Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'c', 0);
		Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'd', 255);
		Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'e', 0);
		Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'f', 0);
		Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'g', 255);
		Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'h', 0);
		Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'i', 0);
		Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'j', 255);
		Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'k', 0);
		Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'l', 0);*/
		//updatePad(200);
		
	new myAsync().execute();

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.activity_main, menu);
		return true;
	}

	@Override
	protected void onStop() {
		super.onStop();
		retriever.release();
	//	updatePad(0);
		Amarino.disconnect(this, ARDUINO_ADDRESS);
	}

	protected void updateLED(ArrayList<ArrayList<Integer>> leds) {

		//if (System.currentTimeMillis() - lastChange > DELAY) {

			 
				Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'a', leds.get(0).get(0));
				Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'b', leds.get(0).get(1));
				Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'c', leds.get(0).get(2));
				Log.w(TAG, "update colors 1 with values " + leds.get(0).get(0) + ", " + leds.get(0).get(1) + ", " + leds.get(0).get(2));
				
				Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'd', leds.get(1).get(0));
				Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'e', leds.get(1).get(1));
				Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'f', leds.get(1).get(2));
				Log.w(TAG, "update colors 2 with values " + leds.get(1).get(0) + ", " + leds.get(1).get(1) + ", " + leds.get(1).get(2));
		
				Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'g', leds.get(2).get(0));
				Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'h', leds.get(2).get(1));
				Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'i', leds.get(2).get(2)); 
				Log.w(TAG, "update colors 3 with values " + leds.get(2).get(0) + ", " + leds.get(2).get(1) + ", " + leds.get(2).get(2));
			
				Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'j', leds.get(3).get(0));
				Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'k', leds.get(3).get(1));
				Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'l', leds.get(3).get(2));
				Log.w(TAG, "update colors 4 with values " + leds.get(3).get(0) + ", " + leds.get(3).get(1) + ", " + leds.get(3).get(2));
				
			
			
		//	lastChange = System.currentTimeMillis();
		//}
	}
	
	protected void updateLEDFade(int r, int g, int b, int red_last, int green_last,int blue_last) {

		if (System.currentTimeMillis() - lastChange > DELAY) {
			
			int fade = 2;
			Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'r', r+red_last/fade);
			Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'g', g+green_last/fade);
			Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'b', b+blue_last/fade);
			Log.w(TAG, "update colors with values " + r + ", " + g + ", " + b);			
			lastChange = System.currentTimeMillis();
		}
		
	}
		
	protected void updatePad(int p) {

			if (System.currentTimeMillis() - lastChange > DELAY) {
				
				Amarino.sendDataToArduino(this, ARDUINO_ADDRESS, 'p', p);
				Log.e(TAG, "update pad with " + p);		
				lastChange = System.currentTimeMillis();
				 
			
		}
	}

	/** Get Feedback for the current position and trigger actions */
	private class myAsync extends AsyncTask<Void, Integer, Void> {
		int duration; //gesammtdauer des videos in ms
		int current = 0;
		
		int last_time = 0;
		int width=0;
		int height=0;
		
		ArrayList<Integer> led1 = new ArrayList<Integer>();
		ArrayList<Integer> led2= new ArrayList<Integer>();
		ArrayList<Integer> led3= new ArrayList<Integer>();
		ArrayList<Integer> led4= new ArrayList<Integer>();
		
		ArrayList<Integer> red1= new ArrayList<Integer>();
		ArrayList<Integer> green1= new ArrayList<Integer>();
		ArrayList<Integer> blue1= new ArrayList<Integer>();
		
		ArrayList<Integer> red2= new ArrayList<Integer>();
		ArrayList<Integer> green2= new ArrayList<Integer>();
		ArrayList<Integer> blue2= new ArrayList<Integer>();
		
		ArrayList<Integer> red3= new ArrayList<Integer>();
		ArrayList<Integer> green3= new ArrayList<Integer>();
		ArrayList<Integer> blue3= new ArrayList<Integer>();
		
		ArrayList<Integer> red4= new ArrayList<Integer>();
		ArrayList<Integer> green4= new ArrayList<Integer>();
		ArrayList<Integer> blue4= new ArrayList<Integer>();
		
		@Override
		protected Void doInBackground(Void... params) {
	
			videoView.start();
			videoView.setOnPreparedListener(new OnPreparedListener() {

			public void onPrepared(MediaPlayer mp) {
					duration = videoView.getDuration();
				}
			});
 
			do {
				//	Log.w(TAG, "im do");
				current = videoView.getCurrentPosition();
				//	Log.e(TAG, "current: "  + current);
				 
	
				
				changeWithMedian();
			
 
				try {
					publishProgress((int) (current * 100 / duration));
					if (mProgressBar.getProgress() >= 100) {
						break;
					}
				} catch (Exception e) {
				}
			} while (mProgressBar.getProgress() <= 100);

			return null;
		}

		

		@Override
		protected void onProgressUpdate(Integer... values) {
			super.onProgressUpdate(values);
			// System.out.println(values[0]);
			mProgressBar.setProgress(values[0]);
		}
		
		
		private int getMedian(ArrayList<Integer> values)
		{
			int median = 0;
			
			Collections.sort(values);
			
			if(values.size() != 0){
					if (values.size() % 2 == 0)
						median = (values.get(values.size() / 2) + values.get(values.size() / 2+1)) / 2;
					else
						median = values.get(values.size() / 2);
			}	
			else
			{
				Log.e(TAG, "getMedian: VALUES is NULL");		
			}
			return median;
		}
		
		
	
		/**Wechselt den Farbwert anhand des Medians */
		private void changeWithMedian()
		{
		
			
	
			/* if(current % 10000 <= 50 && !(current % 20000 <= 50))
			 {
				 Log.e(TAG, "pad on: " + current);
				 updatePad(255);
			 }
			 if(current % 20000 <= 50)
			 {
				 Log.e(TAG, "pad off: " + current);
				 updatePad(0);
			 }*/
			if (current % DELAY <= 25 && last_time <= current) 
			{
				//Log.e(TAG, "in current%1000: " + current);
				last_time = current;

			

			retriever.setDataSource(videoView.getContext(), uri);
			bitmap = retriever.getFrameAtTime(current*1000, MediaMetadataRetriever.OPTION_NEXT_SYNC);	
			width = bitmap.getWidth();
			height = bitmap.getHeight();
			pixels = new int[width*height];		
			
			
			bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
			
		
		//Werte in 4 Sektoren teilen
		

			red1.clear();
			red2.clear();
			red3.clear();
			red4.clear();
			green1.clear();
			green2.clear();
			green3.clear();
			green4.clear();
			blue1.clear();
			blue2.clear();
			blue3.clear();
			blue4.clear();
			
			
			if(pixels.length != 0){
				
				int i=0;
				int untereObergrenze = (int) Math.round(height * 0.2);
				while(i/width <= untereObergrenze) {					
									
					if (i % width <= Math.round(width * 0.2)) 
					{
						for(int c = 0; c < width*0.2; c++)
						{
							red1.add(Color.red(pixels[i]));
							green1.add(Color.green(pixels[i]));
							blue1.add(Color.blue(pixels[i]));
							//i++;
						}
						i+=width * 0.8;
					
					
					if (i % width >= Math.round(width * 0.8) ) 
					{
						for(int c = 0; c < width*0.2; c++)
						{
							red2.add(Color.red(pixels[i]));
							green2.add(Color.green(pixels[i]));
							blue2.add(Color.blue(pixels[i]));
							//i++;
						}
						i+=width*0.2+1;
					}}
					else {
						i++;
						Log.w(TAG, "LERN RECHNEN 1!" + i);
					}
				}
				
				//Log.e(TAG, "i nach oben: " +i);
				i = (int) Math.round(height * 0.8) * width;	
				//Log.e(TAG, "i vor unten: " +i);
				
				while(i < pixels.length){
				 if (i % width <= Math.round(width * 0.2))
					{
						for(int c = 0; c < width*0.2; c++)
						{
							red3.add(Color.red(pixels[i]));
							green3.add(Color.green(pixels[i]));
							blue3.add(Color.blue(pixels[i]));
							//i++;
						}
						i+=width * 0.8;
					
					if (i % width >= Math.round(width * 0.8) )
					{
						for(int c = 0; c < width*0.2; c++)
						{
							red4.add(Color.red(pixels[i]));
							green4.add(Color.green(pixels[i]));
							blue4.add(Color.blue(pixels[i]));
							//i++;
						}
						i+=width * 0.2+1;
						
					}}
					else {
						i++;
						Log.w(TAG, "LERN RECHNEN! 2: " + i);
					}
					
					
					
					/*Log.e(TAG, "pixels[i]: " + pixels[i] );
					// 20% oben links
					if (i % width < width * 0.2 && i / width < height * 0.2) {
						red1.add(Color.red(pixels[i]));
						green1.add(Color.green(pixels[i]));
						blue1.add(Color.blue(pixels[i]));
					}
					// oben rechts
					else if (i % width > width * 0.8 && i / width < height * 0.2) {
						red2.add(Color.red(pixels[i]));
						green2.add(Color.green(pixels[i]));
						blue2.add(Color.blue(pixels[i]));
					}
					// unten links
					else if (i % width < width * 0.2 && i / width > height * 0.8) {
						red3.add(Color.red(pixels[i]));
						green3.add(Color.green(pixels[i]));
						blue3.add(Color.blue(pixels[i]));
					}
					// unten rechts
					else if (i % width > width * 0.8 && i / width > height * 0.8) {
						red4.add(Color.red(pixels[i]));
						green4.add(Color.green(pixels[i]));
						blue4.add(Color.blue(pixels[i]));
					}*/
				}
			
				Log.e(TAG, "durchlauf");
				
				led1.add(this.getMedian(red1));
				led1.add(this.getMedian(green1));
				led1.add(this.getMedian(blue1));
				
				led2.add(this.getMedian(red2));
				led2.add(this.getMedian(green2));
				led2.add(this.getMedian(blue2));
				
				led3.add(this.getMedian(red3));
				led3.add(this.getMedian(green3));
				led3.add(this.getMedian(blue3));
				
				led4.add(this.getMedian(red4));
				led4.add(this.getMedian(green4));
				led4.add(this.getMedian(blue4));
				
				ArrayList<ArrayList<Integer>> changeLEDs = new ArrayList<ArrayList<Integer>>();
				changeLEDs.add(led1);
				changeLEDs.add(led2);
				changeLEDs.add(led3);
				changeLEDs.add(led4);
		
				//ToDo: check if there is really a change before sending
				updateLED(changeLEDs);
			//	updateLED(2,led2.get(0),led2.get(1),led2.get(2));
			//	updateLED(3,led3.get(0),led3.get(1),led3.get(2));
			//	updateLED(4,led4.get(0),led4.get(1),led4.get(2));
				
				led1.clear();
				led2.clear();
				led3.clear();
				led4.clear();
				changeLEDs.clear();
			}
		
			}
		}}
		
	

	}
